//
//  FQDCyclePageView.m
//  FakeQDaily
//
//  Created by mewxiv on 8/13/16.
//  Copyright © 2016 Xensius. All rights reserved.
//

#import "FQDCyclePageView.h"

@interface FQDCyclePageView () <UIScrollViewDelegate>

// 轮播的scrollView和pageControl控件
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
// 轮播页面数组
@property (nonatomic, strong) NSArray *pageItems;

@property (nonatomic, readonly, assign) CGFloat pageWidth;
@property (nonatomic, readonly, assign) CGFloat pageHeight;

// 自动轮播计时器
@property (nonatomic, strong) NSTimer *timer;
// 是否暂停轮播
@property (nonatomic, assign) BOOL isPause;
// 继续自动轮播时判断之前是否达到自动轮播时间
@property (nonatomic, assign) BOOL readyForNextPage;

@end

@implementation FQDCyclePageView

#pragma mark - View life cycle

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _isPause = NO;
        _readyForNextPage = NO;
        _autoCycleTime = 5.0f;

        UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
        scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        scrollView.pagingEnabled = YES;
        scrollView.bounces = NO;
        scrollView.showsHorizontalScrollIndicator = false;
        scrollView.delegate = self;
        [self addSubview:scrollView];
        self.scrollView = scrollView;

        UIPageControl *pageControl = [[UIPageControl alloc] init];
        [self addSubview:pageControl];
        self.pageControl = pageControl;

    }
    return self;
}

- (void)dealloc
{
    [self.timer invalidate];
    self.timer = nil;
}

- (void)layoutSubviews
{
    NSInteger currentPage = self.pageControl.currentPage;

    [super layoutSubviews];

    [self layoutPageItems];

    // 处理旋转后更新ScrollView的contentOffset为当前页起始位置
    CGPoint contentOffset = self.scrollView.contentOffset;
    contentOffset.x = currentPage * self.pageWidth + self.pageWidth;
    self.scrollView.contentOffset = contentOffset;

    CGSize pcSize = CGSizeMake(self.pageWidth, 20);
    CGPoint pcOrigin = CGPointMake(0, self.pageHeight - pcSize.height * 1.5);
    self.pageControl.frame = (CGRect) {pcOrigin, pcSize};
}

#pragma mark - Getters and Setters
- (CGFloat)pageWidth
{
    return self.scrollView.frame.size.width;
}

- (CGFloat)pageHeight
{
    return self.scrollView.frame.size.height;
}

- (void)setDataSource:(id<FQDCyclePageViewDataSource>)dataSource
{
    _dataSource = dataSource;

    [self reloadData];
}

#pragma mark - Timers

- (void)startTimer
{
    self.timer = [NSTimer scheduledTimerWithTimeInterval:self.autoCycleTime target:self selector:@selector(nextPage:) userInfo:nil repeats:YES];

    // 解决滑动时timer暂停回调的问题
    [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
}

- (void)stopTimer
{
    [self.timer invalidate];
}

- (void)nextPage:(NSTimer *)timer
{
    if (self.isPause) {
        self.readyForNextPage = YES;
        [self stopTimer];
    } else {
        NSInteger actualPage = self.pageControl.currentPage + 1;
        NSInteger nextPage = actualPage + 1;
        CGPoint contentOffset = self.scrollView.contentOffset;
        contentOffset.x = nextPage * self.pageWidth;
        [self.scrollView setContentOffset:contentOffset animated:YES];
        self.readyForNextPage = NO;
    }
}

#pragma mark - UIScrollView Delegate methods
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat correctOffset = scrollView.contentOffset.x - self.pageWidth;
    NSInteger pageIndex = correctOffset / self.pageWidth + 0.5;
    self.pageControl.currentPage = pageIndex;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self stopTimer];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    [self startTimer];
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    [self cycleScroll];
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [self cycleScroll];
}

- (void)cycleScroll
{
    NSInteger actualPage = (self.scrollView.contentOffset.x / self.pageWidth + 0.5);
    NSInteger pageNum = [self.pageItems count];
    if (actualPage == pageNum + 1) {
        [self.scrollView setContentOffset:CGPointMake(self.pageWidth, 0) animated:NO];
    }
    if (actualPage == 0) {
        CGFloat offset = pageNum * self.pageWidth;
        [self.scrollView setContentOffset:CGPointMake(offset, 0) animated:NO];
    }
}

#pragma mark - Other methods

- (void)reloadData
{
    NSInteger pageNum = [self.dataSource numberOfPagesInPageView:self];
    self.pageControl.numberOfPages = pageNum;
    self.pageControl.currentPage = 0;

    [self reloadPageItems];
    [self layoutPageItems];

    self.timer ? [self stopTimer] : nil;
    [self startTimer];
}

// 重新添加页面到scrollView
- (void)reloadPageItems
{
    for (UIView *subview in self.scrollView.subviews) {
        [subview removeFromSuperview];
    }

    NSInteger pageNum = [self.dataSource numberOfPagesInPageView:self];
    NSMutableArray *pageItems = [NSMutableArray arrayWithCapacity:pageNum];
    for (int i = 0; i < pageNum; i++) {
        UIView *pageItem = [[UIView alloc] init];
        UIView *pageContent = [self.dataSource pageView:self viewForPageAtPageIndex:i];
        pageContent.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [pageItem addSubview:pageContent];
        [self.scrollView addSubview:pageItem];
        [pageItems addObject:pageItem];

        UITapGestureRecognizer *tapRecognizer =
            [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pageTapped:)];
        tapRecognizer.numberOfTapsRequired = 1;
        [pageItem addGestureRecognizer:tapRecognizer];

    }
    self.pageItems = [pageItems copy];

    // 首尾重复插入重复页面实现轮播
    if (pageNum > 0) {
        UIView *firstPage = [[UIView alloc] init];
        UIView *firstPageContent = [self.dataSource pageView:self viewForPageAtPageIndex:0];
        firstPageContent.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [firstPage addSubview:firstPageContent];

        UIView *lastPage = [[UIView alloc] init];
        UIView *lastPageContent = [self.dataSource pageView:self viewForPageAtPageIndex:(pageNum - 1)];
        lastPageContent.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        [lastPage addSubview:lastPageContent];

        [self.scrollView insertSubview:lastPage atIndex:0];
        [self.scrollView addSubview:firstPage];
    }

}

- (void)pageTapped:(UIGestureRecognizer *)gr
{
    UIView *page = gr.view;
    NSInteger idx = [self.pageItems indexOfObject:page];
    self.selectPageItemBlock ? self.selectPageItemBlock(idx) : nil;
}

- (void)layoutPageItems
{
    [self.scrollView.subviews enumerateObjectsUsingBlock:
     ^(UIView * _Nonnull view, NSUInteger idx, BOOL * _Nonnull stop) {
        view.frame = CGRectMake(idx * self.pageWidth, 0, self.pageWidth, self.pageHeight);
    }];
    NSInteger actualCount = [self.pageItems count] + 2;
    self.scrollView.contentSize = CGSizeMake(actualCount * self.pageWidth, self.pageHeight);
}

- (void)pauseCycleScroll
{
    self.isPause = YES;
}

- (void)resumeCycleScroll
{
    self.isPause = NO;
    if (!self.timer.isValid && self.readyForNextPage) {
        [self nextPage:nil];
        [self startTimer];
    }
    self.readyForNextPage = NO;
}

@end